#pragma once
#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
using namespace std;
// 服务器往往是禁止拷贝的
using namespace LogModule;
using namespace ThreadPoolModule;

using func_t = function<string(const string &, InetAddr &)>;

const static int defaultsockfd = -1;
const static int backlog = 8;

class TcpServer : public NoCopy
{
public:
    TcpServer(uint16_t port, func_t func)//绑定端口和函数
        : _port(port), _func(func),
          _isrunning(false), _listensockfd(defaultsockfd)
    {
    }
    void Init()//初始化套接字和InetAddr并且绑定下来
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            exit(SOCKET_ERR);
        }
        LOG(LogLevel::INFO) << "socket success" << _listensockfd;
        InetAddr local(_port);
        int n = bind(_listensockfd, local.NeAddPtr(), local.NeAddrLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(LISTEN_ERR);
        }
        LOG(LogLevel::INFO) << "bind success" << _listensockfd;

        n=listen(_listensockfd,backlog);
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"listen error";
            exit(LISTEN_ERR);
        }
        LOG(LogLevel::INFO)<<"listen success:"<<_listensockfd;
    }
    class ThreadData//线程的信息包括:套接字,InetAddr,Tcpserver本身指针
    {
    public:
        ThreadData(int fd, InetAddr &arr, TcpServer *s)//InetAddr用于存储端口和IP
            : sockfd(fd), addr(arr), tsvr(s)
        {
        }
        int sockfd;
        InetAddr addr;
        TcpServer *tsvr;
    };

    void Service(int sockfd, InetAddr &peer)//持续不断地向套接字中读数据，并写入数据
    {
        char buffer[1024];
        while (true)
        {
            ssize_t n =read(sockfd,buffer,sizeof(buffer)-1);
            if(n>0)
            {
                buffer[n]=0;
                LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"#"<<buffer;
                string echo_string = _func(buffer,peer);
                write(sockfd,echo_string.c_str(),echo_string.size());
            }
            else if(n==0)
            {
                LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"推出了";
                close(sockfd);
                break;
            }
            else
            {
                LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"异常...";
                close(sockfd);
                break;
            }
        }
    }
    static void *Routine(void* args)//分离自身线程并启动服务
    {
        pthread_detach(pthread_self());
        ThreadData* td=static_cast<ThreadData*>(args);
        td->tsvr->Service(td->sockfd,td->addr);
        delete td;
        return nullptr;
    }
    void Run()//和客户端握手并且创建线程运行Routine,将ThreadData传给Routine
    {
        _isrunning=true;
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len =sizeof(sockaddr_in);
            int sockfd=accept(_listensockfd,CONV(peer),&len);
            if(sockfd<0)
            {
                LOG(LogLevel::WARNING)<<"accept failure";
                continue;
            }
            InetAddr addr(peer);
            LOG(LogLevel::INFO)<<"accept success,peer addr:"<<addr.StringAddr();

            ThreadData* td=new ThreadData(sockfd,addr,this);
            pthread_t tid;
            pthread_create(&tid,nullptr,Routine,td);
        }
        _isrunning=false;
    }

private:
    uint16_t _port;
    int _listensockfd;
    bool _isrunning;
    func_t _func;
};